package ac.zlf.springmybatis.core.mybatis.domain;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class PageImpl<T> implements Page<T>, Serializable {
    private static final long serialVersionUID = 867755909294344406L;
    private final List<T> content = new ArrayList();
    private final Pageable pageable;
    private final int total;

    public PageImpl(List<T> content, Pageable pageable, int total) {
        if (null == content) {
            throw new IllegalArgumentException("Content must not be null!");
        }
        this.content.addAll(content);
        this.total = total;
        this.pageable = pageable;
    }

    public PageImpl(List<T> content) {
        this(content, null, null == content ? 0 : content.size());
    }

    public Pageable getPageable() {
        return this.pageable;
    }

    public boolean add(T e) {
        throw new UnsupportedOperationException();
    }

    public void add(int index, T element) {
        throw new UnsupportedOperationException();
    }

    public boolean addAll(Collection<? extends T> c) {
        throw new UnsupportedOperationException();
    }

    public boolean addAll(int index, Collection<? extends T> c) {
        throw new UnsupportedOperationException();
    }

    public void clear() {
        throw new UnsupportedOperationException();
    }

    public boolean contains(Object o) {
        return getContent().contains(o);
    }

    public boolean containsAll(Collection<?> c) {
        return getContent().containsAll(c);
    }

    public T get(int index) {
        return getContent().get(index);
    }

    public int indexOf(Object o) {
        return getContent().indexOf(o);
    }

    public boolean isEmpty() {
        return getContent().isEmpty();
    }

    public int lastIndexOf(Object o) {
        return getContent().lastIndexOf(o);
    }

    public ListIterator<T> listIterator() {
        return getContent().listIterator();
    }

    public ListIterator<T> listIterator(int index) {
        return getContent().listIterator(index);
    }

    public boolean remove(Object o) {
        throw new UnsupportedOperationException();
    }

    public T remove(int index) {
        throw new UnsupportedOperationException();
    }

    public boolean removeAll(Collection<?> c) {
        throw new UnsupportedOperationException();
    }

    public boolean retainAll(Collection<?> c) {
        return getContent().retainAll(c);
    }

    public T set(int index, T element) {
        throw new UnsupportedOperationException();
    }

    public int size() {
        return getContent().size();
    }

    public List<T> subList(int fromIndex, int toIndex) {
        return getContent().subList(fromIndex, toIndex);
    }

    public Object[] toArray() {
        return getContent().toArray();
    }

    public <T> T[] toArray(T[] a) {
        return getContent().toArray(a);
    }

    public int getNumber() {
        return this.pageable == null ? 0 : this.pageable.getPageNumber();
    }

    public int getPageSize() {
        return this.pageable == null ? 0 : this.pageable.getPageSize();
    }

    public int getTotalPages() {
        return getPageSize() == 0 ? 0 : (int) Math.ceil(this.total / getPageSize());
    }

    public int getNumberOfElements() {
        return this.content.size();
    }

    public int getTotalElements() {
        return this.total;
    }

    public boolean hasPreviousPage() {
        return getNumber() > 0;
    }

    public boolean isFirstPage() {
        return !hasPreviousPage();
    }

    public boolean hasNextPage() {
        return (getNumber() + 1) * getPageSize() < this.total;
    }

    public boolean isLastPage() {
        return !hasNextPage();
    }

    public Iterator<T> iterator() {
        return this.content.iterator();
    }

    public List<T> getContent() {
        return Collections.unmodifiableList(this.content);
    }

    public boolean hasContent() {
        return !this.content.isEmpty();
    }

    public Sort getSort() {
        return this.pageable == null ? null : this.pageable.getSort();
    }

    public String toString() {
        String contentType = "UNKNOWN";
        if (this.content.size() > 0) {
            contentType = this.content.get(0).getClass().getName();
        }
        return String.format("Page %s of %d containing %s instances", new Object[]{Integer.valueOf(getNumber()), Integer.valueOf(getTotalPages()), contentType});
    }

    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof PageImpl)) {
            return false;
        }
        PageImpl<?> that = (PageImpl) obj;

        boolean totalEqual = this.total == that.total;
        boolean contentEqual = this.content.equals(that.content);
        boolean pageableEqual = this.pageable == null ? false : that.pageable == null ? true : this.pageable.equals(that.pageable);

        return (totalEqual) && (contentEqual) && (pageableEqual);
    }

    public int hashCode() {
        int result = 17;

        result = 31 * result + (this.total ^ this.total >>> 32);
        result = 31 * result + (this.pageable == null ? 0 : this.pageable.hashCode());
        result = 31 * result + this.content.hashCode();

        return result;
    }
}